package com.jiankangjin.transsystem.services.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jiankangjin.common.uuid.IdGenerator;
import com.jiankangjin.httpclient.HttpClient;
import com.jiankangjin.trading.dao.IChannelDao;
import com.jiankangjin.trading.dao.IOrderDataDao;
import com.jiankangjin.trading.dao.IPaymentDataDao;
import com.jiankangjin.trading.entity.ChannelEntity;
import com.jiankangjin.trading.entity.OrderDataEntity;
import com.jiankangjin.trading.entity.PaymentDataEntity;
import com.jiankangjin.transsystem.common.Constant;
import com.jiankangjin.transsystem.services.PayOrderServices;
import com.jiankangjin.transsystem.util.StringUtil;
import com.jiankangjin.transsystem.util.TimeUtil;
import com.jiankangjin.transsystem.vo.PayOrderBean;
import com.jiankangjin.transsystem.vo.PayOrderVo;

/**
 * 订单支付 业务逻辑服务层接口实现
 * 访问jiankangjin.trading.core数据操作层
 */
@Service
public class PayOrderServicesImpl implements PayOrderServices{
	private static final Log log = LogFactory.getLog(PayOrderServicesImpl.class);
	
	@Autowired
	private IOrderDataDao iOrderDataDao;
	
	@Autowired
	private IPaymentDataDao iPaymentDataDao;
	
	@Autowired
	private IChannelDao iChannelDao;

	/**
	 * 支付接口
	 * @param module_id
	 * @param version
	 * @param local_pay_ssn
	 * @param order_id
	 * @param fee
	 * @param currency
	 * @param channel_id
	 * @param buyer_token
	 * @param buyer_voucher
	 * @param channel_type
	 * @param custom_str
	 * @param sign
	 * @return
	 */
	@Override
	public PayOrderVo payOrder(String module_id, String version,
			String local_pay_ssn, String order_id, String fee, String currency,
			String channel_id, String buyer_token, String buyer_voucher,
			String channel_type, String custom_str) {
		PayOrderVo payOrderVo = new PayOrderVo();
		ChannelEntity channel = iChannelDao.selectByPrimaryKey(channel_id);
		if (StringUtil.isEmpty(channel_id) || null == channel) {
			payOrderVo.setResp_status(Constant.RESP_STAT_MSG_0001);
			payOrderVo.setResp_msg("支付渠道编号错误");
			return payOrderVo;
		}
		
		// 2. TODO:验证模块签名
		// module_id/module_key
		
		// 不能支付的情况
		// 1) 订单不存在
		OrderDataEntity orderData = iOrderDataDao.selectByPrimaryKey(order_id);
		if(orderData==null){
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0002);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0002);
			return payOrderVo;
		}
		// 2) 订单已过期。 order_stat = 0002
		long time = Long.parseLong(TimeUtil.getTime());
		long order_expr_time = Long.parseLong(orderData.getOrdExprTime());
		if(time > order_expr_time){
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0010);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0010);
			return payOrderVo;
		}
		// 3) 订单已作废。 order_stat = 0003
		if (orderData.getOrdStat().equals(Constant.ORD_STAT_CODE_CANCEL)) {
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0011);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0011);
			return payOrderVo;
		}
		// 4) 订单正在支付 有渠道正在支付。 order_stat = 0001
		if (orderData.getOrdStat().equals(Constant.ORD_STAT_CODE_PROCESSING)) {
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0012);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0012);
			return payOrderVo;
		}
		// 5) 订单没有要支付的金额。 支付金额 >（可支付金额 = 订单金额-已支付金额+已退款金额）
		int _fee = StringUtil.Str2int(fee);
		int order_amt = StringUtil.Str2int(orderData.getOrdAmt());
		int pay_amt = StringUtil.Str2int(orderData.getPayAmt());
		int refund_amt = Integer.parseInt(orderData.getRefundAmt());
		int can_pay_amt = order_amt - pay_amt + refund_amt;
		if (can_pay_amt == 0) {
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0013);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0013);
			return payOrderVo;
		} else if(_fee > can_pay_amt) {
			log.error(order_amt + " - " + pay_amt + " + " + refund_amt +" = " + can_pay_amt);
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0014);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0014 + ",当前订单你最多可以支付" + can_pay_amt);
			return payOrderVo;
		}
		// 3. 操作主表数据:OrderData,PaymentData,OrderDetailData,DiagData
		// 3.0插入OrderData
		OrderDataEntity orderEntity = new OrderDataEntity();
		orderEntity.setId(order_id);
		orderEntity.setOrdStat(Constant.ORD_STAT_CODE_PROCESSING);
		if(1 != iOrderDataDao.update(orderEntity)){
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_9999);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_9999 + ",更新订单表失败");
			return payOrderVo;
		}
		
		// 3.1 插入PaymentData
		PaymentDataEntity paymentData = new PaymentDataEntity();
		paymentData.setId(IdGenerator.getId());//生成的支付ID
		paymentData.setPayDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));//生成支付日期
		paymentData.setOrdSysId(order_id);//交易系统订单ID
		paymentData.setMerId(orderData.getMerId());//商户ID
		paymentData.setRefundStat(Constant.REFUND_STAT_CODE_NOTREFUND);//退款状态=0000
		paymentData.setRefundCnt("0");//累计退款次数=0
		paymentData.setRefundAmt("0");//累计退款金额=0
		paymentData.setPayMthd(Constant.PAY_METHOD_0001);//支付类型
		paymentData.setPayChnl(channel_id);//支付渠道编号
		paymentData.setMerOrdId(orderData.getMerOrdId());//商户订单号
		paymentData.setOrdCry(orderData.getOrdCry());//订单币种
		paymentData.setOrdAmt(orderData.getOrdAmt());//订单金额
		paymentData.setPayCry(Constant.CURRENCY_156);//支付币种
		paymentData.setPayAmt(fee);//本次支付金额
		paymentData.setPayStat(Constant.PAY_STAT_CODE_INIT);//支付状态=0000
		paymentData.setPayRegTime(TimeUtil.getTime());//支付发起时间
		if(1 != iPaymentDataDao.insert(paymentData)){
			payOrderVo.setResp_status(Constant.RESP_STAT_CODE_9999);
			payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_9999+",插入支付流水表失败");
			return payOrderVo;
		}
		
		//组装业务Bean
		PayOrderBean payOrderBean = new PayOrderBean();
		payOrderBean.setModuleId(module_id);
		payOrderBean.setVersion(version);
		payOrderBean.setLocalPaySsn(local_pay_ssn);
		payOrderBean.setOrderId(order_id);
		payOrderBean.setFee(fee);
		payOrderBean.setCurrency(currency);
		payOrderBean.setChannelId(channel_id);
		payOrderBean.setBuyerToken(buyer_token);
		payOrderBean.setBuyerVoucher(buyer_voucher);
		payOrderBean.setChannelType(channel_type);
		payOrderBean.setCustomStr(custom_str);
		payOrderBean.setOrderData(orderData);
		payOrderBean.setPaymentData(paymentData);
		
		// 4. 根据数据配置，路由渠道
		payOrderBean = doRoute(channel, payOrderBean);
/*
		// 4. 渠道路由,操作附表数据:不包含以上四表的其它渠道特有的附属表
		try {
			payOrderVo = doRoute(channel_id,payOrderVo);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(this, e);
			String errorMsg = Constant.RESP_STAT_MSG_9999+",渠道路由反射异常";
			return CommonResponse.formatErrorResult(Constant.RESP_STAT_CODE_9999,errorMsg);
		}
*/
		
		// 5. 调完渠道以后 更新主表信息
		// 5.1 更新PaymentData
		PaymentDataEntity newPaymentData = payOrderBean.getPaymentData();
		iPaymentDataDao.update(newPaymentData);//--更新支付表
		
		// 5.2 更新OrderData
		OrderDataEntity newOrderData = payOrderBean.getOrderData();
		PaymentDataEntity newPamentData = payOrderBean.getPaymentData();
		if (newPamentData.getPayStat().equals(Constant.PAY_STAT_CODE_SUCCESS)) {
			//本次支付成功的处理
			// 1) 订单状态 和 订单支付状态
			long allFee = Integer.parseInt(newOrderData.getOrdAmt());//订单总金额
			long agoFee = 0;//历史已支付总金额
			PaymentDataEntity example = new PaymentDataEntity();
			example.setOrdSysId(newOrderData.getId());
			example.setPayMthd(Constant.PAY_METHOD_0001);
			example.setPayStat(Constant.PAY_STAT_CODE_SUCCESS);
			List<PaymentDataEntity> listPaymentData = iPaymentDataDao.listByEntity(example);
			for (int i = 0; i < listPaymentData.size(); i++) {
				agoFee += Integer.parseInt(listPaymentData.get(i).getPayAmt());//历史支付成功记录金额累加 
			}
			log.info("订单金额=" + allFee +" 历史共支付=" + agoFee + " 其中本次支付=" + fee);
			if (agoFee != 0) {
				if(agoFee < allFee) {//部分支付
					newOrderData.setPayStat(Constant.ORD_PAY_STAT_CODE_PARTSUCCESS);
					newOrderData.setOrdStat(Constant.ORD_STAT_CODE_INIT);
				} else {//全部支付
					newOrderData.setOrdStat(Constant.ORD_STAT_CODE_SUCCESS);
					newOrderData.setPayStat(Constant.ORD_PAY_STAT_CODE_SUCCESS);
					newOrderData.setOrdFinTime(TimeUtil.getTime());//支付完成时间
				}
			}
			// 2) 已支付金额
			newOrderData.setPayAmt(""+agoFee);
		} else {
			//本次支付失败的处理
			if (null != orderData.getFeeAmt() || "".equals(orderData.getFeeAmt())) {
				newOrderData.setPayAmt("0");
			}
		}
		// 3) 订单状态不变
		// 4) 支付记录编号
		String payId = "";
		if (orderData.getPayId()==null) {
			payId = newPaymentData.getId();
		} else {
			payId = orderData.getPayId() + "," +newPaymentData.getId();
			if (payId.length()>=256) {
				payId = payId.substring(33, payId.length());
			}
		}
		newOrderData.setPayId(payId);
		// 5) 订单支付时间
		newOrderData.setOrdPayTime(TimeUtil.getTime());//支付时间
		iOrderDataDao.update(newOrderData);//--更新订单表
		
		// 6. 返回给网关或者前置的结果集
		payOrderVo.setResp_status(Constant.RESP_STAT_CODE_0000);
		payOrderVo.setResp_msg(Constant.RESP_STAT_MSG_0000);
		payOrderVo.setSub_deal_ssn(newPaymentData.getId());
		payOrderVo.setSub_deal_stauts(payOrderBean.getSubDealStatus());
		payOrderVo.setSub_deal_msg(payOrderBean.getSubDealMsg());
		payOrderVo.setResp_msg("处理成功");
		payOrderVo.setCustom_str(payOrderBean.getCustomStr());
		payOrderVo.setSign("transSystemyessign");
		return payOrderVo;
	}
	/**
	 * 渠道路由-支付
	 */
	public PayOrderBean doRoute(ChannelEntity channel, PayOrderBean payOrderBean) {
		String path = "http://" + channel.getProjectUrl() + ":"
				+ channel.getProjectPort() + "/" + channel.getProjectName()
				+ "/pay";
		log.info("路由至渠道："+ path + " (" + channel.getChannelFeeType() + " " + channel.getMethodVersion() +")");
		Map<String, Object> params = new HashMap<>();
		params.put("channel_fee_type", channel.getChannelFeeType());
		params.put("version", channel.getMethodVersion());
		params.put("pay_ssn_id", payOrderBean.getPaymentData().getId());
		params.put("order_id", payOrderBean.getOrderId());
		params.put("pay_fee", payOrderBean.getFee());
		params.put("pay_cry", payOrderBean.getCurrency());
		params.put("buyer_token", payOrderBean.getBuyerToken());
		params.put("buyer_voucher", payOrderBean.getBuyerVoucher());
		params.put("subjet", "");
		params.put("remark", "");
		params.put("buyer_name", "");
		params.put("buyer_email", "");
		params.put("seller_name", "");
		params.put("seller_email", "");
		params.put("expand_json", payOrderBean.getCustomStr());
		params.put("sign", "transSystem_pay_doRoute_sign");
		log.info("调渠道支付：" + params);
		Map<String, Object> payMap = HttpClient.getInstance().doPOSTgetHashMap(path, params);
		log.info("渠道支付返回：" + payMap);
		
		payOrderBean.getPaymentData().setPayChnl(channel.getId());
		if (payMap == null) {
			payOrderBean.getPaymentData().setPayStat(Constant.PAY_STAT_CODE_FAIL);
			payOrderBean.setSubDealStatus(Constant.PAY_STAT_CODE_FAIL);
			payOrderBean.setSubDealMsg(Constant.PAY_STAT_MSG_FAIL);
			return payOrderBean;
		}
		if (Constant.RESP_STAT_CODE_0000.equals(payMap.get("resp_status"))) {
			payOrderBean.getPaymentData().setPayCry((String)payMap.get("pay_cry"));
			payOrderBean.getPaymentData().setPayChnlSeq((String)payMap.get("pay_chnl_seq"));
			payOrderBean.getPaymentData().setPayFinTime((String)payMap.get("pay_fin_time"));
			payOrderBean.getPaymentData().setPayChnlPos((String)payMap.get("Pay_chnl_pos"));
			payOrderBean.getPaymentData().setPayChnlMer((String)payMap.get("Pay_chnl_mer"));
			payOrderBean.getPaymentData().setPayChnlFee((String)payMap.get("Pay_chnl_fee"));
			payOrderBean.getPaymentData().setPayUser((String)payMap.get("pay_user"));
			payOrderBean.getPaymentData().setPayStat((String)payMap.get("sub_deal_status"));
			payOrderBean.setSubDealStatus((String)payMap.get("sub_deal_status"));
			payOrderBean.setSubDealMsg((String)payMap.get("sub_deal_msg"));
			payOrderBean.setCustomStr((String)payMap.get("expand_json"));
		} else {
			payOrderBean.getPaymentData().setPayStat(Constant.PAY_STAT_CODE_FAIL);
			payOrderBean.setSubDealStatus((String)payMap.get("resp_status"));
			payOrderBean.setSubDealMsg((String)payMap.get("resp_msg"));
		}
		return payOrderBean;
	}
}
